package com.geek.gkpush.ctrl.biz.impl;

import com.geek.gkpush.ctrl.facade.UniversalCtrlFacade;
import com.geek.gkpush.ctrl.facade.abs.AbstractResponse;
import com.geek.gkpush.ctrl.facade.bean.ExecUniversalCtrlReq;
import com.geek.gkpush.ctrl.facade.bean.ExecUniversalCtrlResp;
import com.geek.gkpush.framework.groovy.GroovyClassLoaderWrapper;
import com.geek.gkpush.framework.groovy.UniversalExecRunnable;
import com.geek.gkpush.util.excp.ExcpStackUtils;
import com.geek.gkpush.util.json.JacksonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * <h1>万能管控服务 Facade 实现类。</h1><br/>
 *
 * <h1><br/><a href="https://u.geekbang.org/subject/arch3/100614201">Java 业务架构实战营：https://u.geekbang.org/subject/arch3/100614201</a></h1><br/><h1><a href="https://gitee.com/ylimhhmily/BizArchPracticeCamp">Java 业务架构实战营代码地址：https://gitee.com/ylimhhmily/BizArchPracticeCamp</a></h1><br/><h1><a href="https://u.geekbang.org/subject/java4th/1001148?source=app_share">高级 Java 工程体系课 2023 版：https://u.geekbang.org/subject/java4th/1001148?source=app_share</a></h1><br/><h1><a href="https://time.geekbang.org/column/intro/100312101?tab=catalog">Dubbo 源码剖析与实战：https://time.geekbang.org/column/intro/100312101?tab=catalog</a></h1>
 *
 * @author hmilyylimh
 * ^_^
 * @version 0.0.1
 * ^_^
 * @date 2023/9/29 15:30
 */
@Slf4j
@Component
@DubboService
public class UniversalCtrlFacadeImpl implements UniversalCtrlFacade {

    private static final String PREFIX = "Universal_Ctrl";

    @Autowired
    private GroovyClassLoaderWrapper groovyClassLoaderWrapper;

    @Override
    public AbstractResponse execUniversalCtrl(ExecUniversalCtrlReq req) {
        String newBeanName = null;
        try {
            // 尝试移除内存中已有的实例对象
            newBeanName = String.join("_", PREFIX, req.getBeanName());
            groovyClassLoaderWrapper.removeBean(newBeanName);

            // 动态编译获取实例bean对象
            UniversalExecRunnable execRunnable =
                    (UniversalExecRunnable) groovyClassLoaderWrapper.getBean(newBeanName, req.getBeanScriptBase64());

            // 动态执行，返回执行结果
            String execResult = JacksonUtils.toJson(execRunnable.exec(req.getArgs()));

            // 返回响应
            return AbstractResponse.ok(new ExecUniversalCtrlResp(execResult));
        } catch (Exception e) {
            log.error("execUniversalCtrl error.", e);
            return AbstractResponse.excp(new ExecUniversalCtrlResp(ExcpStackUtils.getStackTrace(e)));
        } finally {
            groovyClassLoaderWrapper.removeBean(newBeanName);
        }
    }
}